package com.itheima.reggie.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.reggie.common.CustomException;
import com.itheima.reggie.common.R;
import com.itheima.reggie.dto.DishDto;
import com.itheima.reggie.entity.*;
import com.itheima.reggie.service.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jacoco.agent.rt.internal_f3994fa.core.internal.flow.IFrame;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @version 1.0
 * @Author 杨旭康
 * @Date 2022/11/3 10:07
 * @question:
 */

@RestController
@RequestMapping("/dish")
@Slf4j
@Api(tags = "菜品相关接口")
public class DishController {

    @Autowired
    private DishService dishService;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 可以使用此注解观察缓存情况
     */
    @Autowired
    private CacheManager cacheManager;


    /**
     * 添加菜品 ===>> 使用数据传输对象dto 来接收
     * dish里只有菜品分类id 一会得用id调分类名
     * 请求 URL: http://localhost:8080/dish
     * 请求方法: POST
     *
     * @param dishDto
     * @return
     */
    @PostMapping
//    @CacheEvict(value = "dishCache",key = "#dishDto.categoryId + '_' + #dishDto.status")
    @CacheEvict(value = "dishCache",allEntries = true)
    @ApiOperation(value = "新增菜品接口")
    public R<String> save(@RequestBody DishDto dishDto) {

        //添加菜品时,数据库的信息会发生改变,但是缓存不会发生改变,
        //为了使缓存和数据库信息保持一致 此处需要删除缓存信息

        log.info(dishDto.toString());
        //一个dishService方法显然不够 直接去service层构造新方法
        dishService.saveWithFlavor(dishDto);

        //删除缓存信息有两种 1.全部删除所有缓存信息 2.根据修改的哪一个category分类的id来进行删除(精确删除)
        //定义 key信息
//        String key = "dish_" + dishDto.getCategoryId() + "_1";
        //精确进行删除
//        redisTemplate.delete(key);

        return R.success("新增菜品成功");
    }

    /**
     * 分页条件查询
     * 请求 URL: http://localhost:8080/dish/page?page=1&pageSize=10&name=123
     * 请求方法: GET
     *
     * @param page
     * @param pageSize
     * @param name
     * @return
     */
    @GetMapping("/page")
    @ApiOperation(value = "分页条件查询")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页记录数",required = true),
            @ApiImplicitParam(name = "name",value = "菜品名称",required = false)
    })
    public R<Page> pageR(int page, int pageSize, String name) {

        Page<DishDto> dishDtoPage = dishService.dishDtoPage(page, pageSize, name);

        return R.success(dishDtoPage);
    }

    /**
     * 修改之前的 回显 ===>> 通过id查询
     * 请求 URL: http://localhost:8080/dish/1588027225527078914
     * 请求方法: GET
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public R<DishDto> get(@PathVariable Long id) {

        DishDto dishDto = dishService.getByIdWithFlavor(id);

        return R.success(dishDto);
    }

    /**
     * 真正执行的修改操作
     * 请求 URL: http://localhost:8080/dish
     * 请求方法: PUT
     *
     * @param dishDto
     * @return
     */
    @PutMapping
    @CacheEvict(value = "dishCache",key = "#dishDto.categoryId + '_' + #dishDto.status")
    public R<String> update(@RequestBody DishDto dishDto) {

        dishService.updateWithFlavor(dishDto);

        //删除缓存信息有两种 1.全部删除所有缓存信息 2.根据修改的哪一个category分类的id来进行删除(精确删除)
        //定义 key信息
//        String key = "dish_" + dishDto.getCategoryId() + "_1";
//        Set keys = redisTemplate.keys("dish_*");
        //全部进行删除
//        redisTemplate.delete(keys);

        return R.success("修改菜品信息成功");
    }

    /**
     * 删除-批量删除
     * 1.状态为1不能删除  2.删除要判断套餐中是否有正在售卖的该菜品 如果有禁止删除  3.删除也要记者把口味表数据删掉
     * 请求 URL: http://localhost:8080/dish?ids=1588027225527078914
     * 请求方法: DELETE
     *
     * @param ids
     * @return
     */
    @DeleteMapping
    @CacheEvict(value = "dishCache",allEntries = true)
    public R<String> remove(@RequestParam List<Long> ids) {

        dishService.removeByIdsWithFlavor(ids);

        //删除缓存信息有两种 1.全部删除所有缓存信息 2.根据修改的哪一个category分类的id来进行删除(精确删除)
        //定义 key信息
//        Set keys = redisTemplate.keys("dish_*");
        //全部进行删除
//        redisTemplate.delete(keys);

        return R.success("菜品信息删除成功~");
    }

    /**
     * 批量起售停售-- TODO 实战内容
     * <p>
     * 请求 URL: http://localhost:8080/dish/status/0?ids=1586692024532234241
     * 请求方法: POST
     * <p>
     * 此判断逻辑较为复杂 --> 停售菜品,套餐也得停售
     * 若该套餐想要起售,则必须满足菜品状态为1
     * <p>
     * ids : 菜品id
     *
     * @param ids
     * @param status
     * @return
     */
    @PostMapping("/status/{status}")
    @CacheEvict(value = "dishCache",allEntries = true)
    public R<String> status(@RequestParam List<Long> ids, @PathVariable String status) {

        /**
         * 判断菜品
         * 菜品如果不包含在套餐当中可以直接停售
         * 如果包含在套餐当中 且套餐售卖状态为 1直接抛业务异常
         */
        dishService.status(status,ids);

        //删除缓存信息有两种 1.全部删除所有缓存信息 2.根据修改的哪一个category分类的id来进行删除(精确删除)
        //定义 key信息
//        Set keys = redisTemplate.keys("dish_*");
        //全部进行删除
//        redisTemplate.delete(keys);

        return R.success("操作成功");
    }

    /**
     * 在套餐分类中根据套餐分类下拉列表和菜品列表 展示菜品
     * 请求 URL: http://localhost:8080/dish/list?categoryId=1397844263642378242
     * 请求方法: GET
     * @param dishDto
     * @return
     */
    @GetMapping("/list")
    @Cacheable(value = "dishCache",key = "#dishDto.categoryId + '_' + #dishDto.status")
//    public R<List<Dish>> listR(Dish dish) {
    public R<List<DishDto>> listR(DishDto dishDto) {

        //重新定义 返回值 缓存和service方法都要使用
        List<DishDto> dishDtoList = null;

        //使用缓存来缓存菜品数据减轻数据库压力
        //缓存数据 肯定是根据分页来进行缓存 即分类id和状态status
        //1.自定义key 跟参数保持一致
        String key = "dish_" + dishDto.getCategoryId() + "_" + dishDto.getStatus();

        //2.调用方法 判断缓存中是否有数据
        dishDtoList = (List<DishDto>) redisTemplate.opsForValue().get(key);
        if (dishDtoList != null) {
            //不等于空 证明缓存中有数据 直接return即可
            return R.success(dishDtoList);
        }

        //调用service查询 集合
        dishDtoList = dishService.listR(dishDto);
        //等于空的话 将数据缓存到redis 第二次调用就不会再走service
        redisTemplate.opsForValue().set(key,dishDtoList);

        return R.success(dishDtoList);
    }








}
